-
Notifications
You must be signed in to change notification settings - Fork 53
add plugin client factory #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The option parameter is arbitrary, there is no way to make plugin clients be interchangeable. Should we define the options? Do we need options at all in the plugin client factory?
src/PluginClientFactory.php
Outdated
namespace Http\Client\Common; | ||
|
||
/** | ||
* Create a PluginClient. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could have a more expressive comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe remove this class comment and only use the one on the interface.
src/PluginClientFactoryInterface.php
Outdated
use Http\Client\HttpClient; | ||
|
||
/** | ||
* Create a PluginClient. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm open to any suggestion :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe:
Create a PluginClient object loaded with an array of plugins. A factory may add or modify the plugins or change the HttpClient.
src/PluginClientFactoryInterface.php
Outdated
* @param Plugin[] $plugins | ||
* @param array $options | ||
* | ||
* @see PluginClient constructor for $options details. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we cannot "see the PluginClient". We are not aware of any client implementation. We should write something like "array of options that are passed to the client."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. There is only one PluginClient without a dedicated interface and this implementation is final. There is no way to write an other PluginClient!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct. I had in mind that one could create ANY PluginClient
with this. But the PluginClientFactoryInterface
creates an instance of the concrete class PluginClient
. That is a huge different from our other *FactoryInterface
s. They create an instance of an interface.
Note: |
TBH, I don't really see the point of this interface. |
I don't see any alternative implementation options, so why an interface? Creating a plugin client is configuration which is always specific to the application, so why standardizing it? |
The idea behind is to use discovery to find a concrete PluginClientFactory. When the bundle profiling is enabled, a profile aware PluginClientFactory is decorates each plugin with a ProfilePlugin and add the StackPlugin at the begining. See php-http/HttplugBundle#109 (comment) for a whole plan details. |
Why do we need a factory to decorate plugins? And why do we have to discover it? I still think it's configuration: when profiling is enabled, hook into DI and wrap plugins, otherwise don't. |
It's all about displaying plugins from 3rd party like php-github-api in the profiler. With such implementation, you can integrate any 3rd party library (which use this interface and the discovery) in the profiler without having any specific code in the 3rd party library, without having a glue bundle and without having to write a line of configuration! |
I updated the PR to add a note in the changelog. I also adressed @Nyholm comments about docblocks. I added in my to do list the puli stuff. Can someone help me with it? EDIT: I think I found what I have to do with puli. Does I need to add some tests related to puli? |
How can I test puli resources declaration? |
This is now updated to provide a solution which does not require |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand better now why we use the callable
. We loose a lot of code and interfaces.
src/PluginClientFactory.php
Outdated
* Set the factory to use. The callable to provide must have the same arguments and return type as | ||
* PluginClientFactory::createClient. | ||
* | ||
* @internal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe state why?
This is used by the HTTPlugBundle to provide a better Symfony integration
src/PluginClientFactory.php
Outdated
*/ | ||
public function createClient($client, array $plugins = [], array $options = []) | ||
{ | ||
$factory = static::$factory ?: function ($client, array $plugins, array $options) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not simply do:
if (static::$factory) {
return $factory($client, $plugins, $options);
}
return new PluginClient($client, $plugins, $options);
It would be easier to read.
Thank you @Nyholm. I addressed all your remarks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good, just fix the travis error
src/PluginClientFactory.php
Outdated
public function createClient($client, array $plugins = [], array $options = []) | ||
{ | ||
if (static::$factory) { | ||
return (static::$factory)($client, $plugins, $options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not allowed in PHP 5.x. ( I just found out)
$func = static::$factory;
return $func($client, $plugins, $options);
// Or: (This might work)
return static::$factory($client, $plugins, $options);
Should be fixed now. Please, don't merge until it's ok on other packages. |
@fbourigault Is this ready to merge? Do @dbu or @sagikazarmark want to have a final review? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand why we need this, but I am still not a huge fan.
/** | ||
* @var callable | ||
*/ | ||
private static $factory; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the workaround for not having an interface? If so, having an interface for this is still less evil. This solution provides zero type safety (even if the support PHP versions do not support return types).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As the stuff is marked internal, we choosed to avoid over engineering and to not use an interface.
I added the |
I will merge this, but we should review it a final time before releasing. Thank you for the comments and thank you for the work on this PR |
if (static::$factory) { | ||
$factory = static::$factory; | ||
|
||
return $factory($client, $plugins, $options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deos simply return static::$factory(...)
not work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only in PHP 7+
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
weird. can you add a comment that this is to work with php 5 and can be removed in 7?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wrong. It doesn't work in any PHP version: "Function name must be a string".
See https://3v4l.org/WA5ek.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alright. then maybe a comment that using it directly does not work at least up to php 7.1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't work too in 7.2.0alpha2. IMHO it doesn't worth to write a comment about something not supported by the language itself.
* | ||
* @return PluginClient | ||
*/ | ||
public function createClient($client, array $plugins = [], array $options = []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this method dynamic but the factory callable static? this means i must instantiate the factory, but i can only set one single callable. why not make the callable an optional constructor argument?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The setFactory is static as we need to change the implementation at runtime when bundle profiling is enabled and, as we aim to do 0config integration, we can't have something non-static here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, i see. maybe a bit of comment in the code would help so we remember in the future ;-)
could we use the class docblock to explain why this factory should be used? |
This is required to display plugins created by 3rd party libraries in the HttplugBundle profiler. See php-http/HttplugBundle#109 (comment) for all puzzle pieces.
To Do